# -*- coding: utf-8 -*-
"""
心理咨询师服务系统 - 认证API
"""

import os
from flask import request, jsonify, current_app
from flask_jwt_extended import (
    jwt_required, get_jwt_identity, create_access_token,
    create_refresh_token, get_jwt
)
from werkzeug.security import check_password_hash
from werkzeug.utils import secure_filename
from app.api.auth import bp
from app.models import User, UserMembership, UserBasicInfo
from app import db
from datetime import datetime
import re
import uuid


@bp.route('/register', methods=['POST'])
def register():
    """用户注册"""
    try:
        data = request.get_json()
        
        # 验证必填字段
        required_fields = ['username', 'email', 'password']
        for field in required_fields:
            if not data.get(field):
                return jsonify({
                    'success': False,
                    'message': f'{field} 是必填字段'
                }), 400
        
        username = data['username'].strip()
        email = data['email'].strip().lower()
        password = data['password']
        phone = data.get('phone', '').strip() if data.get('phone') else None
        
        # 验证用户名格式
        if len(username) < 3 or len(username) > 20:
            return jsonify({
                'success': False,
                'message': '用户名长度必须在3-20个字符之间'
            }), 400
        
        # 验证邮箱格式
        email_pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
        if not re.match(email_pattern, email):
            return jsonify({
                'success': False,
                'message': '邮箱格式不正确'
            }), 400
        
        # 验证密码强度
        if len(password) < 6:
            return jsonify({
                'success': False,
                'message': '密码长度至少6个字符'
            }), 400
        
        # 验证手机号格式（如果提供）
        if phone:
            phone_pattern = r'^1[3-9]\d{9}$'
            if not re.match(phone_pattern, phone):
                return jsonify({
                    'success': False,
                    'message': '手机号格式不正确'
                }), 400
        
        # 检查用户名是否已存在
        if User.query.filter_by(username=username).first():
            return jsonify({
                'success': False,
                'message': '用户名已存在'
            }), 400
        
        # 检查邮箱是否已存在
        if User.query.filter_by(email=email).first():
            return jsonify({
                'success': False,
                'message': '邮箱已被注册'
            }), 400
        
        # 检查手机号是否已存在（如果提供）
        if phone and User.query.filter_by(phone=phone).first():
            return jsonify({
                'success': False,
                'message': '手机号已被注册'
            }), 400
        
        # 创建用户
        user = User(
            username=username,
            email=email,
            phone=phone
        )
        user.set_password(password)
        
        db.session.add(user)
        db.session.flush()  # 获取用户ID
        
        # 创建基础会员信息
        from datetime import date, timedelta
        membership = UserMembership(
            user_id=user.id,
            plan_type='basic',
            start_date=date.today(),
            end_date=date.today() + timedelta(days=36500)  # 100年后过期，相当于永不过期
        )
        
        db.session.add(membership)
        db.session.commit()
        
        # 生成JWT令牌
        access_token, refresh_token = user.generate_tokens()
        
        return jsonify({
            'success': True,
            'message': '注册成功',
            'data': {
                'user': user.to_dict(),
                'access_token': access_token,
                'refresh_token': refresh_token
            }
        }), 201
        
    except Exception as e:
        db.session.rollback()
        current_app.logger.error(f'注册失败: {str(e)}')
        return jsonify({
            'success': False,
            'message': '注册失败，请稍后重试'
        }), 500


@bp.route('/login', methods=['POST'])
def login():
    """用户登录"""
    try:
        data = request.get_json()
        
        # 验证必填字段
        if not data.get('username') or not data.get('password'):
            return jsonify({
                'success': False,
                'message': '用户名和密码不能为空'
            }), 400
        
        username = data['username'].strip()
        password = data['password']
        
        # 查找用户（支持用户名、邮箱、手机号登录）
        user = User.query.filter(
            (User.username == username) |
            (User.email == username) |
            (User.phone == username)
        ).first()
        
        if not user or not user.check_password(password):
            return jsonify({
                'success': False,
                'message': '用户名或密码错误'
            }), 401
        
        if not user.is_active:
            return jsonify({
                'success': False,
                'message': '账户已被禁用，请联系管理员'
            }), 401
        
        # 更新登录信息
        user.update_login_info()
        
        # 生成JWT令牌
        access_token, refresh_token = user.generate_tokens()
        
        return jsonify({
            'success': True,
            'message': '登录成功',
            'data': {
                'user': user.to_dict(),
                'access_token': access_token,
                'refresh_token': refresh_token
            }
        })
        
    except Exception as e:
        current_app.logger.error(f'登录失败: {str(e)}')
        return jsonify({
            'success': False,
            'message': '登录失败，请稍后重试'
        }), 500


@bp.route('/refresh', methods=['POST'])
@jwt_required(refresh=True)
def refresh():
    """刷新访问令牌"""
    try:
        current_user_id = get_jwt_identity()
        user = User.get_by_id(current_user_id)
        
        if not user or not user.is_active:
            return jsonify({
                'success': False,
                'message': '用户不存在或已被禁用'
            }), 401
        
        # 生成新的访问令牌
        access_token = create_access_token(
            identity=user.id,
            additional_claims={'type': 'user'}
        )
        
        return jsonify({
            'success': True,
            'message': '令牌刷新成功',
            'data': {
                'access_token': access_token
            }
        })
        
    except Exception as e:
        current_app.logger.error(f'令牌刷新失败: {str(e)}')
        return jsonify({
            'success': False,
            'message': '令牌刷新失败'
        }), 500


@bp.route('/logout', methods=['POST'])
@jwt_required()
def logout():
    """用户登出"""
    try:
        # 获取当前JWT令牌
        jti = get_jwt()['jti']
        
        # TODO: 将令牌加入黑名单（需要Redis支持）
        # blacklist.add(jti)
        
        return jsonify({
            'success': True,
            'message': '登出成功'
        })
        
    except Exception as e:
        current_app.logger.error(f'登出失败: {str(e)}')
        return jsonify({
            'success': False,
            'message': '登出失败'
        }), 500


@bp.route('/profile', methods=['GET', 'PUT'])
@jwt_required()
def profile():
    """获取或更新用户信息"""
    current_user_id = get_jwt_identity()
    user = User.get_by_id(current_user_id)
    
    if not user:
        return jsonify({
            'success': False,
            'message': '用户不存在'
        }), 404
    
    if request.method == 'GET':
        return jsonify({
            'success': True,
            'data': {
                'user': user.to_dict(include_relationships=True)
            }
        })
    
    elif request.method == 'PUT':
        try:
            data = request.get_json()
            
            # 可更新的基本字段
            basic_fields = ['email', 'phone']
            # 可更新的扩展字段
            extended_fields = ['real_name', 'gender', 'birth_date', 'profession', 'education', 'bio']
            
            # 验证数据
            errors = []
            
            # 检查邮箱唯一性
            if 'email' in data and data['email'] != user.email:
                email = data['email'].strip().lower()
                email_pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
                if not re.match(email_pattern, email):
                    errors.append('邮箱格式不正确')
                elif User.query.filter(User.email == email, User.id != user.id).first():
                    errors.append('邮箱已被其他用户使用')
            
            # 检查手机号唯一性
            if 'phone' in data and data['phone'] != user.phone:
                phone = data['phone'].strip() if data['phone'] else None
                if phone:
                    phone_pattern = r'^1[3-9]\d{9}$'
                    if not re.match(phone_pattern, phone):
                        errors.append('手机号格式不正确')
                    elif User.query.filter(User.phone == phone, User.id != user.id).first():
                        errors.append('手机号已被其他用户使用')
            
            # 验证出生日期
            if 'birth_date' in data and data['birth_date']:
                try:
                    birth_date = datetime.strptime(data['birth_date'], '%Y-%m-%d').date()
                    if birth_date > datetime.now().date():
                        errors.append('出生日期不能是未来的日期')
                except ValueError:
                    errors.append('出生日期格式不正确')
            
            if errors:
                return jsonify({
                    'success': False,
                    'message': '；'.join(errors)
                }), 400
            
            # 更新基本字段
            for field in basic_fields:
                if field in data:
                    setattr(user, field, data[field])
            
            # 更新扩展字段（存储在UserBasicInfo中）
            for field in extended_fields:
                if field in data:
                    user.set_basic_info(field, data[field])
            
            db.session.commit()
            
            return jsonify({
                'success': True,
                'message': '个人信息更新成功',
                'data': {
                    'user': user.to_dict(include_relationships=True)
                }
            })
            
        except Exception as e:
            db.session.rollback()
            current_app.logger.error(f'更新个人信息失败: {str(e)}')
            return jsonify({
                'success': False,
                'message': '更新失败，请稍后重试'
            }), 500


@bp.route('/change-password', methods=['POST'])
@jwt_required()
def change_password():
    """修改密码"""
    try:
        current_user_id = get_jwt_identity()
        user = User.get_by_id(current_user_id)
        
        if not user:
            return jsonify({
                'success': False,
                'message': '用户不存在'
            }), 404
        
        data = request.get_json()
        current_password = data.get('current_password')
        new_password = data.get('new_password')
        
        if not current_password or not new_password:
            return jsonify({
                'success': False,
                'message': '当前密码和新密码不能为空'
            }), 400
        
        # 验证当前密码
        if not user.check_password(current_password):
            return jsonify({
                'success': False,
                'message': '当前密码不正确'
            }), 400
        
        # 验证新密码
        if len(new_password) < 6:
            return jsonify({
                'success': False,
                'message': '新密码长度至少6个字符'
            }), 400
        
        # 更新密码
        user.set_password(new_password)
        db.session.commit()
        
        return jsonify({
            'success': True,
            'message': '密码修改成功'
        })
        
    except Exception as e:
        db.session.rollback()
        current_app.logger.error(f'修改密码失败: {str(e)}')
        return jsonify({
            'success': False,
            'message': '修改密码失败，请稍后重试'
        }), 500


@bp.route('/upload-avatar', methods=['POST'])
@jwt_required()
def upload_avatar():
    """上传头像"""
    try:
        current_user_id = get_jwt_identity()
        user = User.get_by_id(current_user_id)
        
        if not user:
            return jsonify({
                'success': False,
                'message': '用户不存在'
            }), 404
        
        # 检查是否有文件上传
        if 'avatar' not in request.files:
            return jsonify({
                'success': False,
                'message': '没有上传文件'
            }), 400
        
        file = request.files['avatar']
        if file.filename == '':
            return jsonify({
                'success': False,
                'message': '没有选择文件'
            }), 400
        
        # 验证文件类型
        allowed_extensions = {'png', 'jpg', 'jpeg', 'gif'}
        if not ('.' in file.filename and 
                file.filename.rsplit('.', 1)[1].lower() in allowed_extensions):
            return jsonify({
                'success': False,
                'message': '仅支持PNG、JPG、JPEG、GIF格式的图片'
            }), 400
        
        # 验证文件大小（2MB）
        file.seek(0, 2)  # 移动到文件末尾
        file_size = file.tell()
        file.seek(0)  # 重置文件指针
        
        if file_size > 2 * 1024 * 1024:  # 2MB
            return jsonify({
                'success': False,
                'message': '文件大小不能超过2MB'
            }), 400
        
        # 生成唯一文件名
        file_ext = file.filename.rsplit('.', 1)[1].lower()
        filename = f"{user.id}_{uuid.uuid4().hex[:8]}.{file_ext}"
        
        # 确保上传目录存在
        upload_dir = os.path.join(current_app.root_path, 'static', 'uploads', 'avatars')
        os.makedirs(upload_dir, exist_ok=True)
        
        # 保存文件
        file_path = os.path.join(upload_dir, filename)
        file.save(file_path)
        
        # 删除旧头像文件（如果存在）
        old_avatar = user.avatar
        if old_avatar:
            old_file_path = os.path.join(
                current_app.root_path, 'static', 
                old_avatar.lstrip('/')
            )
            if os.path.exists(old_file_path):
                try:
                    os.remove(old_file_path)
                except OSError:
                    pass
        
        # 更新数据库中的头像路径
        avatar_url = f"/static/uploads/avatars/{filename}"
        user.set_basic_info('avatar', avatar_url)
        
        db.session.commit()
        
        return jsonify({
            'success': True,
            'message': '头像上传成功',
            'data': {
                'avatar_url': avatar_url
            }
        })
        
    except Exception as e:
        db.session.rollback()
        current_app.logger.error(f'头像上传失败: {str(e)}')
        return jsonify({
            'success': False,
            'message': '头像上传失败，请稍后重试'
        }), 500


@bp.route('/check-unique', methods=['POST'])
@jwt_required()
def check_unique():
    """检查字段唯一性"""
    try:
        current_user_id = get_jwt_identity()
        data = request.get_json()
        field = data.get('field')
        value = data.get('value')
        
        if not field or not value:
            return jsonify({
                'success': False,
                'message': '字段名和值不能为空'
            }), 400
        
        # 检查支持的字段
        if field not in ['username', 'email', 'phone']:
            return jsonify({
                'success': False,
                'message': '不支持的字段'
            }), 400
        
        # 检查唯一性
        query = User.query.filter(getattr(User, field) == value)
        query = query.filter(User.id != current_user_id)
        exists = query.first() is not None
        
        return jsonify({
            'success': True,
            'data': {
                'field': field,
                'value': value,
                'exists': exists,
                'available': not exists
            }
        })
        
    except Exception as e:
        current_app.logger.error(f'检查唯一性失败: {str(e)}')
        return jsonify({
            'success': False,
            'message': '检查失败，请稍后重试'
        }), 500